require(['rx', 'rx.binding', 'rx.time', 'rx.dom'], function (Rx) {

    var coords = document.querySelector('#coordinates');
    var delta = document.querySelector('#delta');
    var buffer = document.querySelector('#buffer');

    // One and only one subscription
    var mousemove = Rx.DOM.fromEvent(document, 'mousemove');

    // Simple coordinates
    var d1 = mousemove.subscribe(function (e) {
      coords.innerHTML = e.clientX + ',' + e.clientY;
    });

    // Calculate deltas between two mouse movements
    var d2 = mousemove.zip(
      mousemove.skip(1),
      function (l, r) {
        return { clientX: r.clientX - l.clientX, clientY: r.clientY - l.clientY };
      })
      .subscribe(function (e) {
        delta.innerHTML = e.clientX + ',' + e.clientY;
      }
    );

    // Get the last 500ms worth of mouse moves or 10, whichever comes first
    var d3 = mousemove.bufferWithTimeOrCount(500, 10).subscribe(function (e) {
      while(buffer.firstChild) {
          buffer.removeChild(buffer.firstChild);
      }

      var node, elem, i, len;
      for(i = 0, len = e.length; i < len; i++) {
          elem = e[i];
          node = document.createElement('li');
          node.innerHTML = elem.clientX + ',' + elem.clientY;
          buffer.appendChild(node);
      }

    });
});
